Возможно проблема в способностях или строках, близзарды че только не сломали и нужно ждать стабильной версии игры где вылечат 99% глюков, багов и завезут максимальную совместимость со старыми картами.
Блин - видел очень давно похожую реализацию, но походу 100500 людей так и не научились это делать, написать чтоли самому...
Суть - для продажи предметов, войск, всяких древ талантов - используйте спеллбук + способности на основе - поставка ресурсов.
Помещаем в спеллбук до 11 способностей на основе "Поставка ресусов" - это аналог канала, настраивается приказ и прочее, но самое главное есть поля - стоймость золотом, стоймость деревом, т.е эта абилка может требовать не только ману но и золото с деревом. Так же там стоит вкладка, заряд игрока владельца - очень важная настройка:
Заряд игрока владельца включен - тогда за каст ресурсы будут списыватся только у игрока владельца юнита, при этом неважно что вашим юнитом управляет другой игрок.
Заряд игрока владельца выключен - тогда при касте этой абилки ресурсы будут списыватся со счета игрока, который и отдал приказ, это даже можно отследить, но немного геморойно:
Суть: делаем триггер который срабатывает на приказ каста поставки ресурсов, или события юнит начинает каст способности, условия по вкусу и действия - создать еще 1 триггер, в события которого добавить - ресурсы игрока N изменились (для каждого игрока способного купить), условием - ресурсов стало меньше на стоймость каста абилки, и действие - выключить триггер, записать GetTriggerPlayer() в глобальную переменную или в еще куда, это и будет наш игрок который кликнул на поставку ресурсов, ну и далее утилизируем триггер, удаляя действия. Можно написать все действия в условии, тогда не придется удалять действия.
Так можно отследить кто кастанул абилку поставки ресурсов если юнитом управляют несколько игроков.
Настройки интерфейса хранятся в файле war3mapSkin.txt, что появляется в архиве карты при изменении какого-либо значения в разделе Дополнительно -> Игровой интерфейс.
Этот файл можно закинут в папку import проекта wurst, он заменит собой оригинальный в процессе сборки. Минус такого подхода - локализация. Изменяя значения игрового интерфейса в редакторе, автоматически создаются строки локализации в файле war3map.wts для новых значений. С wurst это придется делать вручную.
Только редачить положение стандартных, чтобы создавать свои элементы нужен либо клиент Renderedge либо у ребят приближенных к Личу (Караулов и Анрайз), по факту есть библиотека dll позволяющая отрисовывать фреймы. но её в живую так и не видел. Это глубокие дебри чтобы туда влазить.
Как выяснилось у Близард формат карт нормалей немного другой. Красный и зелёный канал поменяны местами, причём красный(который зелёный) ещё и инвертирован. Это и не OpenGL и не DirectX. Зачем они так сделали - вопрос открытый.
ох =)
расскажу, что если прочитать все 500 комментариев про мемхак, то там есть 1 нормальный ответ про то как его включить
Мне потребовалось 3 раза прочитать чтобы врубиться в это, все 500 комментов
Так вот он правильный ответ: Для запуска мемхака нужно отказать от Cjass сняв галочку EnableAdicParser а во вкладке vJass поставить DisableScriptOpt
Советую запустить сначала карту по отлову урона на мемхаке проверить на сохраняемость, если всё получается, тогда уже переносить мемхак в свою карту
Можно не делать новую способность на основе геройского инвентаря, а просто настроить способность рюкзака, а именно - включить параметр "может использовать предметы".
Но у обоих этих способов есть главный недостаток - книги повышающие статы при использовании не героями ведут к крашу игры - это нужно учитывать и либо убирать книги либо делать систему, которая не давала бы книгам попасть в руки не героям. В принципе, при достаточном уровне навыков можно полностью заменить это кастомной системой, которая позволяла бы не просто подбирать такие предметы, но и делать это просто проходя мимо, без клика на сам предмет и без добавления инвентаря каждому юниту. Но это не самая простая задача.
Talgar2, как я понял, это заготовка, так как не понял, что должна способность делать)
Но чтобы работало то, что ты делаешь через wait, должно выглядеть так
P. S. Запамятовал, если способность для кампании или одиночной игры, то можно не делать, но если для многопользовательской игры и подразумевает частое использование, то надо бы сделать переменную (массив) для сохранения позиций, а в конце триггера также все удалять их через custom script. Подробнее уточнят те, кто на многопользовательских картах специализируется, так как я больше по кампаниям.
Так, могу посоветовать следующие кампании: Обычные кампании (как в warcraft-e) - "Рассвет Эльфов Крови", "Тени Ненависти", "Проклятие Отрекшихся", "Пришествие Орды". Кампании в жанре RPG - "День Дракона", "Последний Друид", "Повелитель Кланов", "Последний Друид", "Joe's Quest", "Deandra's Tale", "Mordork's Quest", "Call Of The Swarm", но последняя еще в разработке. Кампания-головоломка - "Последний Хранитель".
Все эти кампании можешь найти на этом сайте.
ВНЕЗАПНО это делается одним действием: Игра - Enable/Disable Drag-Selection (настроенное на Disable drag-selection functionality (disable drag-selection box)).
Reach, каким образом делается перевоплощение в твоей карте?
Через способность, улучшение или триггерно заменой одного юнита на другой?
Мне кажется, должно сработать через Casting unit.
Я делал через способность.
Сначала нужно создать переменную типа Боевая единица.
Потом установить ей значение - тот юнит, который будет перевоплощаться.
Привязать камеру к юниту (то есть уже к переменной).
Когда юнит применяет способность, поменять значение переменной на Casting unit.
Прикрепить обратно камеру к переменной-юниту.
Обозначения на скрине: Unit [10] - это тот самый юнит
Способность Смена оружия - сделана на основе способности друида ночных эльфов с флагом "Непрерываемый" для того, чтобы можно было перевоплощаться обратно и не терять при этом предметы.
Вобщем озарение как всегда пришло внезапно - понял что GetSpellAbilityUnit срабатывает на дамми и записывает в массив его, а не цель щита. Просто передвинул махинации с дамми в конец функции Actions. Всё отменно работает. Всем спасибо все свободны
Только дебаффы ядовитых стрел могут стакатся, но даммик обязан иметь дальнюю атаку (при условии что у разных абилок ядовитых стрел будут разные баффы в настройках).
Так же можно юзать таймер и ауру торнадо как написали выше, ну если уж совсем нужен сложный бафф как дефолтный - то тут триггер и немного гемора с мемхаком, зато полный комплект параметров (мигает иконка в статусе перед завершением время действия, бафф спадает с цели после диспела, смерти (у цели крест перерождения или аналог), складывается или не складывается в зависимости от кода).
Пример не рекомендуемый к повторению
function FormatAirportTrainingBar takes integer fp_n returns string
local string str = ""
if ( fp_n <= 0 ) then
return str
endif
loop
exitwhen fp_n < 10
if ( udg__TempBarStyle == 0 ) then
set str = str + "''''''''''"
else
set str = str + "||||||||||||||||||||"
endif
set fp_n = fp_n - 10
endloop
loop
exitwhen fp_n <= 0
if ( udg__TempBarStyle == 0 ) then
set str = str + "'"
else
set str = str + "||"
endif
set fp_n = fp_n - 1
endloop
return str
endfunction
function UpdateAirportTrainingBar takes texttag tt, integer fp_nTick, integer fp_nTickMax returns nothing
local integer nProgress
local integer nLen
local string strTT1
local string strTT2
if ( tt == null ) then
call BJDebugMsg( "text tag hDZzRwuZxFQcXqaMPnML null" )
return
endif
set nLen = R2I( I2R( fp_nTickMax ) / 300 * 100 )
set nProgress = R2I( I2R( nLen ) / fp_nTickMax * fp_nTick )
set strTT1 = "" + FormatAirportTrainingBar( nProgress )
set strTT2 = FormatAirportTrainingBar( nLen - nProgress ) + ""
call SetTextTagText( tt, "|cff0080c0" + strTT1 + "|r|cffff0000" + strTT2 + "|r", 0.023 )
endfunction
function Get_Staff_of_Purification takes unit runner returns item
set bj_forLoopAIndex = 0
set bj_lastCreatedItem = null
if GetUnitAbilityLevel( runner, 'Arun' ) == 0 then
return null
endif
loop
exitwhen bj_forLoopAIndex > 5
set bj_lastCreatedItem = UnitItemInSlot( runner, bj_forLoopAIndex )
if GetItemTypeId( bj_lastCreatedItem ) == 'I01A' then
return bj_lastCreatedItem
endif
set bj_forLoopAIndex = bj_forLoopAIndex + 1
endloop
return bj_lastCreatedItem
endfunction
function Trig_RunnerDamageDetect_Conditions takes nothing returns boolean
if GetTriggerEventId( ) == EVENT_UNIT_DAMAGED then
return GetEventDamage( ) > 0.00 and GetEventDamageSource( ) != GetTriggerUnit( ) and GetEventDamageSource( ) != DummyAttacker
endif
return true
endfunction
function HealRunner takes nothing returns nothing
local DamageData dd = GetDataBX( GetExpiredTimer( ) )
call UnitRemoveAbility( dd.attacked, 'AMhp' )
call SetUnitState( dd.attacked, UNIT_STATE_LIFE, dd.hp )
call RemoveDataBX( dd.trix )
call DestroyTimer( dd.trix )
call dd.clear( )
call dd.destroy( )
endfunction
function Trig_RunnerDamageLock_Actions takes nothing returns nothing
local TriggerData st = GetDataBX( GetTriggeringTrigger( ) )
local DamageData dd
local eventid id = GetTriggerEventId( )
if id == EVENT_GAME_TIMER_EXPIRED and st.id < st.time and st.attacked != null then
set st.id = st.id + 1
if GetUnitAbilityLevel( st.attacked, 'Bcyc' ) > 0 or GetUnitAbilityLevel( st.attacked, 'Bcy2' ) > 0 then
call SetTextTagPos( st.tt, GetUnitX( st.attacked ) - 60.00, GetUnitY( st.attacked ) - 60.00, 585.00 )
else
call SetTextTagPos( st.tt, GetUnitX( st.attacked ) - 60.00, GetUnitY( st.attacked ) - 60.00, 80.00 + GetUnitFlyHeight( st.attacked ) )
endif
call UpdateAirportTrainingBar( st.tt, 100 - R2I( st.dmg / st.hp * 100.00 ), 100 )
elseif id == EVENT_UNIT_DAMAGED and st.dmg < st.hp then
set dd = DamageData.create( )
set dd.trix = CreateTimer( )
set dd.attacked = st.attacked
set dd.dmg = GetEventDamage( )
set dd.hp = GetUnitState( dd.attacked, UNIT_STATE_LIFE )
call SetDataBX( dd.trix, dd )
call UnitAddAbility( dd.attacked, 'AMhp' )
call SetUnitState( dd.attacked, UNIT_STATE_LIFE, dd.hp + dd.dmg )
call TimerStart( dd.trix, 0.00, false, function HealRunner )
set st.dmg = st.dmg + dd.dmg
else
call UnitRemoveAbility( st.attacked, 'A08L' )
call UnitMakeAbilityPermanent( st.attacked, false, 'A08L' )
call DisableTrigger( st.trg )
call SetTextTagVisibility( st.tt, false )
if not IsUnitDead( st.attacked ) then
call UnitRemoveAbility( st.attacked, 'B00A' )
endif
call RemoveSavedInteger( gg_htb_HashData, ExKeySoPRunner, GetHandleId( st.attacked ) )
call st.RemoveTrigger( )
call st.destroy( )
endif
set id = null
endfunction
function Trig_Staff_of_Purification_Actions takes nothing returns nothing
local TriggerData dd
local unit Runner = GetSpellAbilityUnit( )
local integer RunnerId = GetHandleId( Runner )
local item Staff = LoadItemHandle( gg_htb_HashData, RunnerId, ExKeySoP )
local integer ChargesCount = 0
local trigger trig = LoadTriggerHandle ( gg_htb_HashData, ExAtomShield, RunnerId )
local integer pBuff
if Staff == null then
set Staff = Get_Staff_of_Purification( Runner )
if Staff == null then
//call DisplayTextToPlayer( Player( CrashPlayerNumber ), 0.00, 0.00, I2Sx( 'A01Q', CrashPlayerNumber ) )
call BJDebugMsg( DEBUG + I2Sx( 'A02O', 0 ) + INFO )
return
endif
call SaveBoolean( gg_htb_HashData, RunnerId, ExKeyHasStaff, true )
call SaveItemHandle( gg_htb_HashData, RunnerId, ExKeySoP, Staff )
endif
set ChargesCount = GetItemCharges( Staff )
if ChargesCount < 1 then
set Runner = null
set Staff = null
set trig = null
return
endif
call SetItemCharges( Staff, 0 )
if trig != null then // блокирующие урон способности не складываются.
call TriggerExecute( trig )
set trig = null
endif
set dd = TriggerData.create( )
set dd.attacked = Runner
set dd.pl = GetOwningPlayer( Runner )
set dd.trg = CreateTrigger( )
set dd.trc = TriggerAddCondition( dd.trg, Condition( function Trig_RunnerDamageDetect_Conditions ) )
set dd.tra = TriggerAddAction ( dd.trg, function Trig_RunnerDamageLock_Actions )
set dd.tt = CreateTextTag( )
set dd.hp = 1000.00 * ChargesCount
set dd.dmg = 1.00
set dd.id = 0
set dd.time = 480
set dd.c = 0.03125
call UnitAddAbility( Runner, 'A07E' )
call UnitRemoveAbility( Runner, 'A07E' )
call UnitAddAbility( Runner, 'A08L' )
call UnitMakeAbilityPermanent( Runner, true, 'A08L' )
call SetDataBX( dd.trg, dd )
call SaveInteger( gg_htb_HashData, ExKeySoPRunner, RunnerId, dd )
call TriggerRegisterPlayerEvent( dd.trg, dd.pl, EVENT_PLAYER_LEAVE )
call TriggerRegisterDeathEvent( dd.trg, Runner )
call TriggerRegisterUnitEvent( dd.trg, Runner, EVENT_UNIT_DAMAGED )
call TriggerRegisterTimerEvent( dd.trg, 0.03125, true )
if GetLocalPlayer( ) == dd.pl or IsPlayerAlly( GetLocalPlayer( ), dd.pl ) then
call SetTextTagVisibility( dd.tt, true )
else
call SetTextTagVisibility( dd.tt, false )
endif
set pBuff = GetUnitAbility( dd.attacked, 'B00A' ) + 0x90
set dd.c = TimerGetElapsed( DispTimer )
call WMem( RMem( pBuff ) + 0x4, mR2I( dd.c + 15.10 ) )
call WMem( RMem( pBuff ) + 0x8, mR2I( dd.c + 10.408 ) )
call SetBuffLevel( pBuff - 0x90, ChargesCount )
call UpdateAirportTrainingBar( dd.tt, 100, 100 )
set Runner = null
endfunction
//===========================================================================
function InitTrig_Staff_of_Purification takes nothing returns nothing
set udg__TempBarStyle = 0
endfunction
Выше пример баффа для предмета, который образует щит блокирующий урон, кол-во заблокированного урона и сколько еще заблокирует щит отображается над головой героя, в виде полоски здоровья (только цвет сине-красный). Так же в статуе есть бафф, один в 1 как бафф дефектных способностей вара, не складывается - новый, перебивает старый. И так далее...
Так ты же выключаешь триггер на 18 секунд вот он и не срабатывает.
Поставь условие, что герыч не имеет абилки-пустышки, если не имеет - дать её и через 18 сек забрать и пустить молнию.
Правда я не уверен насчёт того, отловится ли attacking unit через 18 сек вейта, проверь...
Вообще, если устраивает орбом - то даёшь "сферу молний" с эффектом "цепь молний", у которой 18 сек перезарядка(у цепи не у сферы)
WW перестаёт становиться DIS, когда у героя более одной абилки WW
типа что бы ты мог активировать другой, пока работает первый... но разблокировка идёт на все сразу (и на сам себя тоже)
TeX13, можно, сделано в доте для варкравта...
Способов реализации много, от 'ANeg' (способность механика, Enginering Upgrade, рус-Техника), которым можно свапать скиллы, до таймеров которые будут удалять способность у героя а потом вручать ему снова, таким образом скидывая кулдаун, ну и так же хак на пямять, с помощью которого можно менять кулдаун как захочется, щяс все кому не лень юзают эту наработку.
Я бы на вашем месте использовал "Custom Script", то есть вставил локальные переменные на языке jass. Вышло бы приблизительно так:
Вот рабочий триггер. Никаких глобальных переменных. Работает со множествами игроков и юнитов. Не тормозит карту.
В условиях: (Ability being cast) равно "Здесь поставь способность которая применяется на юнита"
Описываю действия:
Создаем локальную переменную юнита
Даем юниту на которого применяется способность "Невидимость", способность "Змеиная ловкость"
В локальную переменную юнита вписываем юнита на которого применена способность
Ждем тридцать секунд, то есть столько времени, сколько у юнита будет доп. способность "Змеиная ловкость"
По истечении времени забираем у юнита доп. способность "Змеиная ловкость"
В пятой строке 'AEev' - это код способности "Змеиная ловкость"
Если что-то не понятно - обращайся. Напоминаю - триггер полностью играбельный! К комментарию добавляю карту с рабочим триггером:
EfReeZe, соответственно, попробуй поставить первый. Если не поможет - напомни мне завтра вечером или на выходных - найду немного времени и посмотрю в редакторе.
есть событие - юнит получает урон. в нём отслеживается как жертва, так и наносящий урон. можно хоть через хэш, хоть через структуру Юнита записывать всё, что угодно. Кто от кого конкретно сколько получил урона, кто кому сколько нанёс, сколько провисел на ком-то бафф яда и т.п. (Сначала был loop, а теперь периодический триггер). Каждые N секунд, перебираешь всех юнитов в массиве или списке, и отслеживаешь всё, что надо.
Структура - Unit. У неё есть двойной список с юнитами и уроном от яда (полученным или нанесённым - зависит от того, у кого будет этот список - у жертв или у тех, кто наносит яд). Типа DoubleList. В DoubleList есть элементы DoubleElement. В каждом таком элементе записаны unit и real (урон от яда от этого юнита). При получении урона от яда перебирается список, если юнит уже есть, урон от него (или ему) прибавляется. Если нет, то создаётся новый элемент с новым юнитом.
Периодически у нужных юнитов эти списки перебираются. Всё.
Никак, очень сложное заклинание (близзарды пряма изощрялись и собирали совещание, как бы это сделать посложнее - Dracolich(c))
Там бафф по сути триггер с особым событием которое запилили специально для этой способности - юнит потерял ману от каста заклинания, до него можно добраться с помощью мемхака - но костыльно и сложно.
Баши и криты можно отловить косвенно, по получению урона \баффа. Но это ненадежный способ, атака обрабатывается в момент замаха и движок узже знает попадет юнит или промажет, забашит или кританет по цели, еще за долго до самого удара. Поэтому самый рациональный способ - триггерные аналоги этих пассивок - крит, ну тупо перед атакой вручает абилку крита со 100% шансом и усе, баш так же. Особо изворотливые могут сделать детект физического урона и сделать баш из дамми каста молотка бурь (нам же надо только отловить сам факт удара) ну а крит посложнее, но тоже вполне реализуемо.
Это событие срабатывает лишь при старте карты, чтобы сделать срабатывание, когда после потасовки остаётся один юнит, логично было бы сделать событие Generic unit Умирает. В условии учитываются не только живые юниты, но и их трупы, пока не разложатся, то есть будет срабатывать событие юнит Умирает, в условии юнитов в области будет больше 1, так как будут считаться мёртвые юниты, триггер так и не будет срабатывать, если через минуту какой-то юнит на карте не умрёт. Потому в условии нужно указывать не просто юнитов в области, а юниты в области matching condition, где поставишь (Matching unit) is alive равно Да. А чтобы не учитывались здания и призванные юниты, нужно вместо условия (Matching unit) is alive равно Да выбрать в низу списка And, появится два условия, в первое ставишь (Matching unit) is alive равно Да, во второе опять And и аналогично выбираешь, (Matching unit) is Здание равно Нет и что-то такое же на призванных (summon).
Только в действии тоже укажи, что живой, не Здание и не призванный, а то кого-то из них может убить.
upd: на скрине идет строгая проверка на равенство 9.0, вероятность срабатывания которой крайне мала потому как мана это не целое число, хоть и отображается в интерфейсе как целое.
Рекомендуемая мной реализация - использовать дополнительный индикатор для проверки того что юнит уже создан и проверять не равна ли мана максимальному значению. Например выдавать зданию пассивную способность-пустышку, отмечающую здание как такое у которого уже есть юнит и пока эта способность у здания есть, не создавать нового сколько бы маны ни было.
на 26 патче это без тригов невозможно
с тригами - система выдачи баффов и скрытые спеллбуки с нужными способностями и их выдача нужным юнитам на нужное время
также в карте замок скиби есть аура, эффекты которой суммируются, но она опять таки триггерная
Способ есть.
Но для этого нужен Warcraft 3 и редактор.
Итого:
открываешь редактор,
открываешь в нем карту
клацаем F9 или просто Проверку карты (там иконка самая последняя в строчке, красная галочка)
Profit...
Внимание! Не все карты так можно открыть, некоторые защищенные и открытию в редакторе не подлежат, а если их восстановить, то они не всегда работоспособны.
создавай пустую модель (dummy) дай ему способности москит, неуязвимость, невосприимчивость к магии, затем через триггер задай максимальную скорость анимации, затем через анимацию задай что бы он проиграл анимацию смерти (death) и через 0,01 секунду задай скорость анимации 100%.
скорее всего эта карта не автора, и автор где-нибудь скачал или попытался взломать. А потом открыл карту с помощью стандартного редактора WE. И у него пишет: не удалось открыть файл основной карты. Эта самая распространенная ошибка. Такая ошибка есть при открытии защищенной карты.
также помню скачивал карту одну с хгм, и не мог открыть. Но открылась только в JNGP. Опен дота с хмг тоже не открывалась в WE, сейчас проверил, вроде открывается.
Еще пример один был связан с UMS плагином. Знакомый скинул карту. Но у меня не открывалась даже с JNGP. а дело было в UMS. в редакторе JNGP есть кучу плагинов, которые снимают ограничение карты, точнее обычного стандарт. редактора. Если в карте, сохраненная в JNGP, вышли за ограничения, то обычный редактор это может не открыть. Мб из-за этого.
Trickster, ну так будет 100р?
В карте испоганен заголовок и хешьтаблица и удалены данные об обьектах, поэтому она не открывается ничем кроме зезулы, но зезула не дает возможность редактировать файлы. Ну собственно я это дело снял, могу восстановить открываемость в редакторе..
Попробуй отключить триггеры, для начала, и затем проверь, запустится ли карта в игре. Особенно те, которые были созданы/редактированы относительно недавно до появления фатала.
» WarCraft 3 / Вылет из лобби
» WarCraft 3 / Трансформация здания
» WarCraft 3 / Интерфейс
» WarCraft 3 / Текстуры.
» WarCraft 3 / Сохранения в карте с мемхаком
» WarCraft 3 / Как обойти ограничение?
» WarCraft 3 / Не удаляется молния
» WarCraft 3 / Анимирование башни
» WarCraft 3 / Не работает очищение сферы молний
» WarCraft 3 / Спелл на основе дамми.
» WarCraft 3 / Предмет=способность
» WarCraft 3 / Вопрос по группам джасс
» Администрация XGM / помогите
» WarCraft 3 / Бинды или как это работает?
» StarCraft 2 / Волны атаки
» WarCraft 3 / длительность способности
» WarCraft 3 / ИИ
» WarCraft 3 / Редактор моделей
» WarCraft 3 / Иконки мультиборда
» WarCraft 3 / Вопрос на засыпку.
» WarCraft 3 / Стак яда
» WarCraft 3 / Не могу открыть карту
» WarCraft 3 / Ошибка при открытии карты